#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "stdlib.h"

void salt(cv::Mat img,int count){
    int i,j = 0;
    for(int k = 0; k < count; k++){
        j = std::rand()%img.cols;
        i = std::rand()%img.rows;
        if(img.type() == CV_8UC1){
            img.at<uchar>(i,j) = 255;
        }else if(img.type() == CV_8UC3){
//          need nail down the row and column avaiable
            img.at<cv::Vec3b>(i,j)[0] = 255;
            img.at<cv::Vec3b>(i,j)[1] = 255;
            img.at<cv::Vec3b>(i,j)[2] = 255;
        }
    }
}

cv::Mat test_resize(cv::Mat img)
{
    cv::Mat img1;
    cv::resize(img,img1,cv::Size(50,50));
    cv::imshow("img1",img1);

    return img1;
}

void test_mat_()
{
    cv::Mat img = cv::imread("/home/iroan-ubuntu16/Project/Coding/GraduationProjectCode/logo.jpg");
    cv::Mat_<uchar> img2(img);
    salt(img,5000);
    cv::imshow("img",img);
    img2(10,10) = 0;
    cv::imshow("img2",img2);
    cv::waitKey(0);
}

void ReduceColor()
{
    for(int i,j = 0; i < 255; i++){
        j = i / 64 * 64 + 62 / 2;
        std::cout<<"i = "<<i<<",j = "<<j<<std::endl;
    }
}

void ReduceColor(cv::Mat img, int div)
{
//    获取一行像素值的个数
    int nc = img.cols * img.channels();
//    获取像素矩阵的行数
    int nr = img.rows;
    for(int j = 0; j < nr; j++){
//        获取图像矩阵中一行的像素数据的首地址
        uchar * data = img.ptr<uchar>(j);
//        对一行中的每个像素进行“减色”
        for(int i = 0; i < nc; i++){
            *data = *data/div * div + div/2;
//            指针从一行移动到下一行
            data++;
        }
    }
}

void test_ReduceColor()
{
    cv::Mat img = cv::imread("/home/iroan-ubuntu16/Project/Coding/GraduationProjectCode/iuc.jpg");
    cv::resize(img,img,cv::Size(),0.5,0.5);
    cv::imshow("2017-03-08img",img);
    cv::imwrite("2017-03-08img.jpg",img);
    ReduceColor(img,4);
    cv::imshow("2017-03-08img_div_4",img);
    cv::imwrite("2017-03-08img_div_4.jpg",img);

    ReduceColor(img,16);
    cv::imshow("2017-03-08img_div_16",img);
    cv::imwrite("2017-03-08img_div_16.jpg",img);

    ReduceColor(img,64);
    cv::imshow("2017-03-08img_div_64",img);
    cv::imwrite("2017-03-08img_div_64.jpg",img);

    cv::waitKey(0);
}

void test_method_attribute()
{
    cv::Mat img = cv::imread("/home/iroan-ubuntu16/Project/Coding/GraduationProjectCode/iuc.jpg");
//    attribute
    std::cout<<"step="<<img.step<<std::endl;
    std::cout<<"cols="<<img.cols<<std::endl;
    std::cout<<"rows="<<img.rows<<std::endl;

//        method
//    std::cout<<"step()="<<img.step()<<std::endl;
    std::cout<<"elemSize()="<<img.elemSize()<<std::endl;
    std::cout<<"channels()="<<img.channels()<<std::endl;
    std::cout<<"total()="<<img.total()<<std::endl;
}

void ReduceColorWithIterator(cv::Mat img,int div)
{
    //    创建迭代器对象
    //      方法一
        cv::MatIterator_<cv::Vec3b> iter_start;
        cv::MatIterator_<cv::Vec3b> iter_end;
    //      方法二
//    cv::Mat_<cv::Vec3b>::iterator iter_start;
//    cv::Mat_<cv::Vec3b>::iterator iter_end;

//    指定迭代器位置
    iter_start = img.begin<cv::Vec3b>();
    iter_end = img.end<cv::Vec3b>();

//    使用
    for(; iter_start != iter_end; ++iter_start){
        (*iter_start)[0] = (*iter_start)[0] / div * div + div/2;
        (*iter_start)[1] = (*iter_start)[1] / div * div + div/2;
        (*iter_start)[2] = (*iter_start)[2] / div * div + div/2;
    }
}

void test_iterator_scan_img()
{
    cv::Mat img = cv::imread("/home/iroan-ubuntu16/Project/Coding/GraduationProjectCode/iuc.jpg");
    cv::resize(img,img,cv::Size(),0.5,0.5);
    ReduceColorWithIterator(img,8);
    cv::imshow("img_8",img);
    cv::imwrite("2017-03-09img_8.jpg",img);

    ReduceColorWithIterator(img,32);
    cv::imshow("img_32",img);
    cv::imwrite("2017-03-09img_32.jpg",img);

    ReduceColorWithIterator(img,64);
    cv::imshow("img_64",img);
    cv::imwrite("2017-03-09img_64.jpg",img);
    cv::waitKey(0);
}

void test_run_time()
{
    int start = cv::getTickCount();
    test_iterator_scan_img();
    int count = (cv::getTickCount() - start)/cv::getTickFrequency();
    std::cout<<"count="<<count<<std::endl;
}


void Sharpen(const cv::Mat &img, cv::Mat & res){
    res.create(img.size(),img.type());
//    获取图像通道数
    int nchannals = img.channels();
//    处理所有行
    for(int j = 1; j < img.rows - 1; j++){
        const uchar * previous = img.ptr<const uchar>(j-1);
        const uchar * current = img.ptr<const uchar>(j);
        const uchar * next = img.ptr<const uchar>(j+1);

//        获取输出行的地址
        uchar * output = res.ptr<uchar>(j);

/*
*  saturate_cast模板函数的作用是为了防止计算结果数据的溢出
* int i = nchannals; 直接跳过了一行的第一个像素的数据值（含三个通道的值）
* (img.cols - 1) * nchannals; （一整行总的像素- 行末像素）× 一行像素的通道数
* current[i - nchannals]: 当前像素的左边像素
* current[i + nchannals]: //当前像素的右边像素
*/

        for(int i = nchannals; i < (img.cols - 1) * nchannals; i++){
            *output ++= cv::saturate_cast<uchar>(5 * current[i] - current[i - nchannals] - current[i + nchannals] - previous[i] - next[i]);
//            *output ++= cv::saturate_cast<uchar>(8 * current[i] - current[i - nchannals] - current[i + nchannals] - previous[i] - next[i]);
        }
    }

/*
 * 处理无法计算的像素
 * setTo(): 对该行的所有元素赋值
 * cv::Scalar():指定像素值
 *
 */
    res.row(0).setTo(cv::Scalar(0));
    res.row(res.rows - 1).setTo(cv::Scalar(0));
    res.col(0).setTo(cv::Scalar(0));
    res.col(res.cols - 1).setTo(cv::Scalar(0));
}

void test_sharpen()
{
    cv::Mat img = cv::imread("/home/iroan-ubuntu16/Project/Coding/GraduationProjectCode/iuc.jpg");
    cv::Mat img_sharpen;
    cv::resize(img,img,cv::Size(),0.5,0.5);
    cv::imshow("img",img);
    cv::imwrite("2017-03-09img.jpg",img);

    Sharpen(img,img_sharpen);
    cv::imshow("img1",img_sharpen);
    cv::imwrite("2017-03-09img_sharpen.jpg",img_sharpen);
    cv::waitKey(0);
}

void test_img_add()
{
    cv::Mat src1 = cv::imread("/home/iroan-ubuntu16/Project/Coding/GraduationProjectCode/src1.jpg");
    cv::Mat src2 = cv::imread("/home/iroan-ubuntu16/Project/Coding/GraduationProjectCode/src2.jpg");
    cv::Mat src3;

//    cv::addWeighted(src1,0.7,src2,0.9,0.,src3);
    src3 = 0.7 * src1 + 0.7 * src2;
    cv::imshow("src1",src1);
    cv::imshow("src2",src2);
    cv::imshow("src3",src3);
    cv::waitKey(0);
}

int main(){
//    test_resize();
//    test_mat_();
//    test_ReduceColor();
//    test_method_attribute();
//    test_run_time();
//    test_sharpen();

    test_img_add();
    return 0;
}
